import requests
import base64
import json
import cv2
import numpy as np
from PIL import Image
import io
import os
import time
from typing import Tuple, Dict, Any
import tkinter as tk
from tkinter import filedialog, messagebox, ttk

class FireDetectionSystem:
    """基于Ollama Gemma3模型的火灾检测系统"""
    
    def __init__(self, ollama_url: str = "http://localhost:11434", model_name: str = "gemma3:latest", debug: bool = False):
        """
        初始化火灾检测系统
        
        Args:
            ollama_url: Ollama服务地址
            model_name: 使用的模型名称
            debug: 是否启用调试模式
        """
        self.ollama_url = ollama_url
        self.model_name = model_name
        # 使用generate API（与test_api_call.py保持一致）
        self.api_url = f"{ollama_url}/api/generate"
        self.debug = debug
        
    def check_ollama_connection(self) -> bool:
        """检查Ollama服务是否可用"""
        try:
            response = requests.get(f"{self.ollama_url}/api/tags", timeout=5)
            return response.status_code == 200
        except requests.exceptions.RequestException:
            return False
    
    def handle_chinese_path(self, path: str) -> str:
        """
        处理中文路径编码问题
        
        Args:
            path: 文件路径
            
        Returns:
            处理后的路径
        """
        if not path:
            return path
            
        try:
            # 检查路径是否包含中文字符
            if any('\u4e00' <= char <= '\u9fff' for char in path):
                # 包含中文字符，确保使用正确的编码
                import sys
                if sys.platform == 'win32':
                    # Windows系统，尝试使用系统默认编码
                    try:
                        return path.encode('cp936').decode('cp936')
                    except:
                        return path.encode('utf-8').decode('utf-8')
                else:
                    # 其他系统，使用UTF-8
                    return path.encode('utf-8').decode('utf-8')
            else:
                # 不包含中文字符，直接返回
                return path
        except Exception as e:
            print(f"路径处理警告: {e}")
            return path
    
    def encode_image_to_base64(self, image_path: str) -> str:
        """
        将图片编码为base64字符串
        
        Args:
            image_path: 图片文件路径
            
        Returns:
            base64编码的图片字符串
        """
        try:
            # 使用PIL读取图片，然后转换为base64
            from PIL import Image
            import io
            
            # PIL对中文路径支持更好
            with Image.open(image_path) as img:
                # 调整图片大小（与测试脚本保持一致）
                img = img.resize((512, 512), Image.Resampling.LANCZOS)
                
                # 转换为RGB格式
                if img.mode == 'RGBA':
                    img = img.convert('RGB')
                elif img.mode != 'RGB':
                    img = img.convert('RGB')
                
                # 保存到内存中的字节流
                img_byte_arr = io.BytesIO()
                img.save(img_byte_arr, format='JPEG', quality=85)
                img_byte_arr = img_byte_arr.getvalue()
                
                return base64.b64encode(img_byte_arr).decode('utf-8')
                
        except Exception as e:
            print(f"图片编码失败: {e}")
            # 备用方案：直接读取文件
            try:
                with open(image_path, "rb") as image_file:
                    return base64.b64encode(image_file.read()).decode('utf-8')
            except Exception as e2:
                print(f"备用编码方案也失败: {e2}")
                return None
    
    def preprocess_image(self, image_path: str, max_size: Tuple[int, int] = (512, 512)) -> str:
        """
        预处理图片：调整大小、压缩等
        
        Args:
            image_path: 图片路径
            max_size: 最大尺寸 (width, height)
            
        Returns:
            处理后的图片路径
        """
        try:
            import numpy as np
            from PIL import Image
            import tempfile
            import os
            
            # 使用PIL读取图片，PIL对中文路径支持更好
            try:
                pil_image = Image.open(image_path)
                # 转换为RGB格式（如果是RGBA）
                if pil_image.mode == 'RGBA':
                    pil_image = pil_image.convert('RGB')
                elif pil_image.mode != 'RGB':
                    pil_image = pil_image.convert('RGB')
                
                # 转换为numpy数组
                image = np.array(pil_image)
                # PIL使用RGB，OpenCV使用BGR，需要转换
                image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
                
            except Exception as e:
                print(f"PIL读取失败: {e}")
                # 备用方案：使用numpy直接读取
                with open(image_path, 'rb') as f:
                    image_data = f.read()
                nparr = np.frombuffer(image_data, np.uint8)
                image = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
            
            if image is None:
                raise ValueError("无法读取图片")
            
            # 调整大小
            height, width = image.shape[:2]
            if width > max_size[0] or height > max_size[1]:
                # 保持宽高比
                scale = min(max_size[0]/width, max_size[1]/height)
                new_width = int(width * scale)
                new_height = int(height * scale)
                image = cv2.resize(image, (new_width, new_height))
            
            # 保存处理后的图片 - 使用临时文件名避免中文路径问题
            temp_dir = tempfile.gettempdir()
            # 生成唯一的临时文件名
            import uuid
            temp_filename = f"processed_{uuid.uuid4().hex[:8]}.jpg"
            processed_path = os.path.join(temp_dir, temp_filename)
            
            # 使用PIL保存，避免中文路径问题
            processed_image = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
            processed_image.save(processed_path, 'JPEG', quality=85)
            
            return processed_path
        except Exception as e:
            print(f"图片预处理失败: {e}")
            return image_path
    
    def create_vision_prompt(self, image_base64: str) -> str:
        """
        创建视觉分析提示词
        
        Args:
            image_base64: base64编码的图片
            
        Returns:
            格式化的提示词
        """
        prompt = f"""
请仔细观察这张图片，判断图中是否发生了火灾。

请用中文回答，并详细说明你的判断依据。

如果看到以下情况，请判断为有火灾：
- 明显的火焰、火苗、燃烧现象
- 浓烟、黑烟、烟雾
- 建筑物、车辆、森林等燃烧
- 其他明显的火灾迹象

如果看到以下情况，请判断为无火灾：
- 正常的火源（如蜡烛、炉火、篝火）在安全环境中
- 红色、橙色物体但不是火焰
- 云朵、雾气等自然现象
- 其他非火灾现象

请详细描述你看到的内容，并说明为什么判断为有火灾或无火灾。
"""
        return prompt
    
    def detect_fire_with_ollama(self, image_path: str) -> Dict[str, Any]:
        """
        使用Ollama Gemma3模型检测火灾
        
        Args:
            image_path: 图片路径
            
        Returns:
            检测结果字典
        """
        try:
            # 直接使用PIL编码图片（与test_api_call.py完全一致）
            from PIL import Image
            import io
            
            with Image.open(image_path) as img:
                # 调整图片大小
                img = img.resize((512, 512), Image.Resampling.LANCZOS)
                
                # 转换为base64
                buffer = io.BytesIO()
                img.save(buffer, format='JPEG', quality=85)
                image_base64 = base64.b64encode(buffer.getvalue()).decode('utf-8')
                
                if self.debug:
                    print(f"✅ 图片编码成功，大小: {len(image_base64)} 字符")
            
            # 创建提示词 - 要求大模型直接输出"是"或"否"
            prompt = "请仔细观察这张图片，判断图中是否发生了火灾。请直接回答：是 或 否。"
            
            # 准备请求数据（与test_api_call.py完全一致）
            payload = {
                "model": "gemma3:latest",
                "prompt": prompt,
                "images": [image_base64],
                "stream": False
            }
            
            # 发送请求
            print("正在分析图片...")
            if self.debug:
                print(f"🔍 调试信息:")
                print(f"   API URL: {self.api_url}")
                print(f"   模型: {self.model_name}")
                print(f"   图片大小: {len(image_base64)} 字符")
                print(f"   请求数据: {json.dumps(payload, ensure_ascii=False, indent=2)}")
            
            response = requests.post(
                self.api_url,
                json=payload,
                timeout=60
            )
            
            if response.status_code == 200:
                result = response.json()
                response_text = result.get('response', '')
                
                # 调试信息
                if self.debug:
                    print(f"🔍 调试信息:")
                    print(f"   完整响应: {result}")
                    print(f"   提取的文本: {response_text}")
                
                # 直接根据大模型的"是"或"否"回答进行判断
                response_lower = response_text.lower().strip()
                
                # 改进的判断逻辑：基于回答的确定性和关键词分析
                response_lower = response_text.lower().strip()
                
                # 火灾相关关键词
                fire_keywords = ['火', '燃烧', '火焰', '烟雾', '浓烟', '火灾', '着火', '烧', '爆炸']
                non_fire_keywords = ['安全', '正常', '无火', '没有火', '不是火', '非火', '正常', '平静']
                
                # 确定性词汇
                certainty_keywords = ['确定', '肯定', '明显', '清楚', '明显', '绝对', '一定']
                uncertainty_keywords = ['可能', '似乎', '好像', '大概', '或许', '不确定', '模糊']
                
                # 计算关键词匹配度
                fire_score = sum(1 for keyword in fire_keywords if keyword in response_text)
                non_fire_score = sum(1 for keyword in non_fire_keywords if keyword in response_text)
                certainty_score = sum(1 for keyword in certainty_keywords if keyword in response_text)
                uncertainty_score = sum(1 for keyword in uncertainty_keywords if keyword in response_text)
                
                # 基于关键词判断是否有火灾
                if fire_score > non_fire_score:
                    has_fire = True
                    base_confidence = 0.6 + (fire_score * 0.1)  # 0.6-0.9
                elif non_fire_score > fire_score:
                    has_fire = False
                    base_confidence = 0.6 + (non_fire_score * 0.1)  # 0.6-0.9
                else:
                    # 如果关键词分数相等，检查明确的"是"或"否"
                    if '是' in response_text and '否' not in response_text:
                        has_fire = True
                        base_confidence = 0.8
                    elif '否' in response_text and '是' not in response_text:
                        has_fire = False
                        base_confidence = 0.8
                    else:
                        # 模糊回答
                        has_fire = False  # 默认无火灾（更安全）
                        base_confidence = 0.5
                
                # 根据确定性调整置信度
                if certainty_score > 0:
                    confidence = min(0.95, base_confidence + 0.1)
                elif uncertainty_score > 0:
                    confidence = max(0.3, base_confidence - 0.2)
                else:
                    confidence = base_confidence
                
                # 确保置信度在合理范围内
                confidence = max(0.3, min(0.95, confidence))
                
                # 调试信息
                if self.debug:
                    print(f"🔍 改进的判断逻辑:")
                    print(f"   大模型回答: {response_text.strip()}")
                    print(f"   火灾关键词分数: {fire_score}")
                    print(f"   非火灾关键词分数: {non_fire_score}")
                    print(f"   确定性分数: {certainty_score}")
                    print(f"   不确定性分数: {uncertainty_score}")
                    print(f"   最终判断: {'有火灾' if has_fire else '无火灾'}")
                    print(f"   置信度: {confidence:.2f}")
                
                # 直接返回大模型的原始输出
                return {
                    "raw_response": response_text,
                    "has_fire": has_fire,
                    "confidence": confidence,
                    "image_path": image_path,
                    "description": response_text,
                    "analysis_details": {
                        "detection_method": "enhanced_keyword_analysis",
                        "model_response": response_text,
                        "fire_keywords_found": fire_score,
                        "non_fire_keywords_found": non_fire_score,
                        "certainty_score": certainty_score,
                        "uncertainty_score": uncertainty_score,
                        "base_confidence": base_confidence,
                        "final_confidence": confidence,
                        "api_format": "generate",
                        "enhanced_analysis": True
                    }
                }
            else:
                return {
                    "error": f"API请求失败: {response.status_code}",
                    "has_fire": False,
                    "confidence": 0.0
                }
                
        except Exception as e:
            return {
                "error": f"检测过程中发生错误: {str(e)}",
                "has_fire": False,
                "confidence": 0.0
            }
    
    def batch_detect(self, image_folder: str) -> Dict[str, Any]:
        """
        批量检测文件夹中的图片
        
        Args:
            image_folder: 图片文件夹路径
            
        Returns:
            批量检测结果
        """
        results = {}
        supported_formats = ('.jpg', '.jpeg', '.png', '.bmp', '.tiff', '.webp')
        
        try:
            # 处理中文路径
            image_folder = self.handle_chinese_path(image_folder)
            
            # 获取文件夹中的所有文件
            files = os.listdir(image_folder)
            
            image_files = [f for f in files 
                          if f.lower().endswith(supported_formats)]
            
            if not image_files:
                return {"error": "文件夹中没有找到支持的图片格式"}
            
            print(f"找到 {len(image_files)} 张图片，开始批量检测...")
            
            for i, image_file in enumerate(image_files, 1):
                # 构建完整路径
                image_path = os.path.join(image_folder, image_file)
                
                print(f"正在检测第 {i}/{len(image_files)} 张图片: {image_file}")
                
                result = self.detect_fire_with_ollama(image_path)
                results[image_file] = result
                
                # 添加延迟避免API限制
                time.sleep(1)
            
            return results
            
        except Exception as e:
            return {"error": f"批量检测失败: {str(e)}"}
    
    def print_detection_result(self, result: Dict[str, Any]):
        """打印检测结果"""
        print("\n" + "="*50)
        print("火灾检测结果")
        print("="*50)
        
        if "error" in result:
            print(f"❌ 错误: {result['error']}")
            return
        
        print(f"📁 图片路径: {result.get('image_path', 'N/A')}")
        print(f"🔥 检测到火灾: {'是' if result.get('has_fire', False) else '否'}")
        print(f"🎯 置信度: {result.get('confidence', 0.0):.2f}")
        
        if 'fire_indicators' in result:
            print(f"🔍 火灾指标: {', '.join(result['fire_indicators'])}")
        
        if 'safety_level' in result:
            safety_emoji = {"low": "🟢", "medium": "🟡", "high": "🔴"}
            print(f"⚠️ 安全等级: {safety_emoji.get(result['safety_level'], '❓')} {result['safety_level']}")
        
        if 'description' in result:
            print(f"📝 详细描述: {result['description']}")
        
        if 'recommendations' in result:
            print(f"💡 安全建议:")
            for rec in result['recommendations']:
                print(f"   • {rec}")
        
        print("="*50)


class FireDetectionGUI:
    """火灾检测图形界面"""
    
    def __init__(self, debug: bool = True):
        self.detector = FireDetectionSystem(debug=debug)
        self.root = tk.Tk()
        self.root.title("火灾检测系统 - Fire Detection System")
        self.root.geometry("800x600")
        self.root.configure(bg='#f0f0f0')
        
        # 设置窗口图标（如果有的话）
        try:
            self.root.iconbitmap("fire_icon.ico")
        except:
            pass
        
        self.setup_ui()
        self.check_ollama_connection()
    
    def setup_ui(self):
        """设置用户界面"""
        # 主标题
        title_frame = tk.Frame(self.root, bg='#f0f0f0')
        title_frame.pack(pady=20)
        
        title_label = tk.Label(
            title_frame, 
            text="🔥 火灾检测系统", 
            font=("Arial", 24, "bold"),
            fg='#d32f2f',
            bg='#f0f0f0'
        )
        title_label.pack()
        
        subtitle_label = tk.Label(
            title_frame,
            text="基于Ollama Gemma3模型的智能火灾检测",
            font=("Arial", 12),
            fg='#666666',
            bg='#f0f0f0'
        )
        subtitle_label.pack(pady=(5, 0))
        
        # 状态显示
        self.status_frame = tk.Frame(self.root, bg='#f0f0f0')
        self.status_frame.pack(pady=10)
        
        self.status_label = tk.Label(
            self.status_frame,
            text="状态: 检查Ollama连接中...",
            font=("Arial", 10),
            bg='#f0f0f0'
        )
        self.status_label.pack()
        
        # 按钮框架
        button_frame = tk.Frame(self.root, bg='#f0f0f0')
        button_frame.pack(pady=20)
        
        # 选择图片按钮
        self.select_image_btn = tk.Button(
            button_frame,
            text="📁 选择图片",
            command=self.select_image,
            font=("Arial", 12, "bold"),
            bg='#2196f3',
            fg='white',
            padx=20,
            pady=10,
            relief='raised',
            bd=2,
            cursor='hand2'
        )
        self.select_image_btn.pack(side=tk.LEFT, padx=10)
        
        # 选择文件夹按钮
        self.select_folder_btn = tk.Button(
            button_frame,
            text="📂 选择文件夹",
            command=self.select_folder,
            font=("Arial", 12, "bold"),
            bg='#4caf50',
            fg='white',
            padx=20,
            pady=10,
            relief='raised',
            bd=2,
            cursor='hand2'
        )
        self.select_folder_btn.pack(side=tk.LEFT, padx=10)
        
        # 清空结果按钮
        self.clear_btn = tk.Button(
            button_frame,
            text="🗑️ 清空结果",
            command=self.clear_results,
            font=("Arial", 12, "bold"),
            bg='#ff9800',
            fg='white',
            padx=20,
            pady=10,
            relief='raised',
            bd=2,
            cursor='hand2'
        )
        self.clear_btn.pack(side=tk.LEFT, padx=10)
        
        # 进度条
        self.progress_frame = tk.Frame(self.root, bg='#f0f0f0')
        self.progress_frame.pack(pady=10, fill='x', padx=20)
        
        self.progress = ttk.Progressbar(
            self.progress_frame,
            mode='indeterminate',
            length=400
        )
        self.progress.pack()
        
        # 结果显示区域
        result_frame = tk.Frame(self.root, bg='#f0f0f0')
        result_frame.pack(fill='both', expand=True, padx=20, pady=10)
        
        # 创建滚动文本框
        text_frame = tk.Frame(result_frame, bg='#f0f0f0')
        text_frame.pack(fill='both', expand=True)
        
        self.result_text = tk.Text(
            text_frame,
            wrap=tk.WORD,
            font=("Consolas", 10),
            bg='#ffffff',
            fg='#333333',
            relief='sunken',
            bd=2
        )
        
        # 添加滚动条
        scrollbar = tk.Scrollbar(text_frame, orient="vertical", command=self.result_text.yview)
        self.result_text.configure(yscrollcommand=scrollbar.set)
        
        self.result_text.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")
        
        # 底部信息
        info_frame = tk.Frame(self.root, bg='#f0f0f0')
        info_frame.pack(side='bottom', fill='x', pady=10)
        
        info_label = tk.Label(
            info_frame,
            text="支持格式: JPG, PNG, BMP, TIFF, WEBP | 使用Ollama Gemma3模型",
            font=("Arial", 9),
            fg='#666666',
            bg='#f0f0f0'
        )
        info_label.pack()
    
    def check_ollama_connection(self):
        """检查Ollama连接状态"""
        def check():
            if self.detector.check_ollama_connection():
                self.status_label.config(
                    text="状态: ✅ Ollama服务连接正常",
                    fg='green'
                )
                self.select_image_btn.config(state='normal')
                self.select_folder_btn.config(state='normal')
            else:
                self.status_label.config(
                    text="状态: ❌ Ollama服务不可用，请确保Ollama正在运行",
                    fg='red'
                )
                self.select_image_btn.config(state='disabled')
                self.select_folder_btn.config(state='disabled')
                
                # 显示错误对话框
                messagebox.showerror(
                    "连接错误",
                    "无法连接到Ollama服务！\n\n请确保：\n1. Ollama服务正在运行\n2. 已安装gemma3模型\n3. 端口11434未被占用\n\n安装命令:\nollama pull gemma3:latest"
                )
        
        # 在新线程中检查连接
        self.root.after(100, check)
    
    def select_image(self):
        """选择单张图片进行检测"""
        filetypes = [
            ("图片文件", "*.jpg *.jpeg *.png *.bmp *.tiff *.webp"),
            ("JPEG文件", "*.jpg *.jpeg"),
            ("PNG文件", "*.png"),
            ("所有文件", "*.*")
        ]
        
        filename = filedialog.askopenfilename(
            title="选择要检测的图片",
            filetypes=filetypes
        )
        
        if filename:
            # 处理中文路径
            filename = self.detector.handle_chinese_path(filename)
            self.detect_single_image(filename)
    
    def select_folder(self):
        """选择文件夹进行批量检测"""
        folder = filedialog.askdirectory(title="选择包含图片的文件夹")
        
        if folder:
            # 处理中文路径
            folder = self.detector.handle_chinese_path(folder)
            self.detect_folder(folder)
    
    def detect_single_image(self, image_path):
        """检测单张图片"""
        self.start_progress("正在分析图片...")
        
        def detect():
            try:
                result = self.detector.detect_fire_with_ollama(image_path)
                self.display_result(result, image_path)
            except Exception as e:
                self.display_error(f"检测失败: {str(e)}")
            finally:
                self.stop_progress()
        
        # 在新线程中执行检测
        self.root.after(100, detect)
    
    def detect_folder(self, folder_path):
        """检测文件夹中的所有图片"""
        self.start_progress("正在批量检测图片...")
        
        def detect():
            try:
                results = self.detector.batch_detect(folder_path)
                self.display_batch_results(results, folder_path)
            except Exception as e:
                self.display_error(f"批量检测失败: {str(e)}")
            finally:
                self.stop_progress()
        
        # 在新线程中执行检测
        self.root.after(100, detect)
    
    def start_progress(self, message):
        """开始进度条"""
        self.progress.start()
        self.status_label.config(text=f"状态: {message}", fg='blue')
        self.select_image_btn.config(state='disabled')
        self.select_folder_btn.config(state='disabled')
    
    def stop_progress(self):
        """停止进度条"""
        self.progress.stop()
        self.status_label.config(text="状态: ✅ 检测完成", fg='green')
        self.select_image_btn.config(state='normal')
        self.select_folder_btn.config(state='normal')
    
    def display_result(self, result, image_path):
        """显示单张图片的检测结果"""
        self.result_text.delete(1.0, tk.END)
        
        output = f"{'='*60}\n"
        output += f"🔥 火灾检测结果\n"
        output += f"{'='*60}\n"
        output += f"📁 图片路径: {image_path}\n"
        output += f"📅 检测时间: {time.strftime('%Y-%m-%d %H:%M:%S')}\n\n"
        
        if "error" in result:
            output += f"❌ 错误: {result['error']}\n"
        else:
            # 检测结果
            has_fire = result.get('has_fire', False)
            confidence = result.get('confidence', 0.0)
            
            output += f"🔥 检测到火灾: {'是' if has_fire else '否'}\n"
            output += f"🎯 置信度: {confidence:.2f}\n\n"
            
            # 火灾指标
            if 'fire_indicators' in result and result['fire_indicators']:
                output += f"🔍 火灾指标:\n"
                for indicator in result['fire_indicators']:
                    output += f"   • {indicator}\n"
                output += "\n"
            
            # 安全等级
            if 'safety_level' in result:
                safety_emoji = {"low": "🟢", "medium": "🟡", "high": "🔴", "低": "🟢", "中": "🟡", "高": "🔴"}
                emoji = safety_emoji.get(result['safety_level'], '❓')
                output += f"⚠️ 安全等级: {emoji} {result['safety_level']}\n\n"
            
            # 详细描述
            if 'description' in result:
                output += f"📝 详细描述:\n{result['description']}\n\n"
            
            # 安全建议
            if 'recommendations' in result and result['recommendations']:
                output += f"💡 安全建议:\n"
                for rec in result['recommendations']:
                    output += f"   • {rec}\n"
                output += "\n"
            
            # 大模型原始输出
            if 'raw_response' in result:
                output += f"🤖 大模型原始输出:\n{result['raw_response']}\n\n"
            
            # 分析详情
            if 'analysis_details' in result:
                details = result['analysis_details']
                output += f"🔍 分析详情:\n"
                output += f"   检测方法: {details.get('detection_method', 'unknown')}\n"
                if 'fire_keywords_found' in details:
                    output += f"   火灾关键词数量: {details['fire_keywords_found']}\n"
                if 'non_fire_keywords_found' in details:
                    output += f"   非火灾关键词数量: {details['non_fire_keywords_found']}\n"
                if 'json_parsed' in details:
                    output += f"   JSON解析: {'成功' if details['json_parsed'] else '失败'}\n"
                output += "\n"
        
        output += f"{'='*60}\n"
        
        self.result_text.insert(tk.END, output)
        self.result_text.see(tk.END)
        
        # 只在检测到火灾时弹出警告窗口
        if "error" not in result:
            has_fire = result.get('has_fire', False)
            if has_fire:
                messagebox.showwarning(
                    "🚨 火灾警报！",
                    f"在图片中检测到火灾迹象！\n置信度: {result.get('confidence', 0.0):.2f}\n\n请立即采取安全措施！\n\n建议：\n• 立即撤离现场\n• 拨打119报警\n• 保持安全距离"
                )
    
    def display_batch_results(self, results, folder_path):
        """显示批量检测结果"""
        self.result_text.delete(1.0, tk.END)
        
        output = f"{'='*60}\n"
        output += f"📂 批量检测结果\n"
        output += f"{'='*60}\n"
        output += f"📁 文件夹路径: {folder_path}\n"
        output += f"📅 检测时间: {time.strftime('%Y-%m-%d %H:%M:%S')}\n\n"
        
        if "error" in results:
            output += f"❌ 错误: {results['error']}\n"
        else:
            # 统计结果
            total_images = len(results)
            fire_count = sum(1 for r in results.values() if r.get('has_fire', False))
            safe_count = total_images - fire_count
            
            output += f"📊 检测统计:\n"
            output += f"   总图片数: {total_images}\n"
            output += f"   🔥 检测到火灾: {fire_count}\n"
            output += f"   ✅ 安全图片: {safe_count}\n\n"
            
            # 详细结果
            output += f"📋 详细结果:\n"
            for filename, result in results.items():
                has_fire = result.get('has_fire', False)
                confidence = result.get('confidence', 0.0)
                status = "🔥 有火灾" if has_fire else "✅ 安全"
                output += f"   {filename}: {status} (置信度: {confidence:.2f})\n"
            
            output += "\n"
            
            # 如果有火灾，显示详细信息
            fire_images = {k: v for k, v in results.items() if v.get('has_fire', False)}
            if fire_images:
                output += f"⚠️ 检测到火灾的图片:\n"
                for filename, result in fire_images.items():
                    output += f"\n📁 {filename}:\n"
                    if 'fire_indicators' in result and result['fire_indicators']:
                        output += f"   指标: {', '.join(result['fire_indicators'])}\n"
                    if 'description' in result:
                        output += f"   描述: {result['description']}\n"
        
        output += f"{'='*60}\n"
        
        self.result_text.insert(tk.END, output)
        self.result_text.see(tk.END)
        
        # 只在检测到火灾时弹出警告窗口
        if "error" not in results:
            fire_count = sum(1 for r in results.values() if r.get('has_fire', False))
            if fire_count > 0:
                messagebox.showwarning(
                    "🚨 批量检测发现火灾！",
                    f"检测完成！\n\n总图片数: {len(results)}\n检测到火灾: {fire_count}\n安全图片: {len(results) - fire_count}\n\n⚠️ 发现火灾风险，请立即查看详细结果！\n\n建议：\n• 检查相关图片\n• 采取安全措施\n• 联系相关部门"
                )
    
    def display_error(self, error_message):
        """显示错误信息"""
        self.result_text.delete(1.0, tk.END)
        self.result_text.insert(tk.END, f"❌ 错误: {error_message}")
        messagebox.showerror("错误", error_message)
    
    def clear_results(self):
        """清空结果显示"""
        self.result_text.delete(1.0, tk.END)
        self.result_text.insert(tk.END, "结果已清空，请选择图片或文件夹进行检测。\n\n支持的操作：\n• 点击'选择图片'按钮检测单张图片\n• 点击'选择文件夹'按钮批量检测\n• 支持中文路径和文件名")
    
    def run(self):
        """运行GUI"""
        self.root.mainloop()


def main():
    """主函数 - 启动图形界面"""
    print("🔥 火灾检测系统启动")
    print("使用模型: Gemma3 (通过Ollama)")
    print("启动图形界面...")
    
    # 启动图形界面
    app = FireDetectionGUI()
    app.run()


if __name__ == "__main__":
    main()

